Projet Zuul de conception orientée objet en Java d'un jeu d'aventure
Forum des exercices du projet Zuul
Exercice 7.46
Add a transporter room. Whenever the player enters leaves this room, he/she is randomly transported into one of the other rooms.
Note: Coming up with a good design for this task is not
trivial. It might be interesting to discuss design alternatives for this
with other
students. (We discuss design alternatives for this task at the end of Chapter 9. You should read it carefully.)
1) Tenir compte de la lecture du chapitre 9.11 (en particulier getExit() et les classes TransporterRoom et RoomRandomizer).
2) L'exercice 18.5, marqué optionnel jusqu'ici, devient obligatoire préalablement à cet exercice ; mais vous n'êtes pas obligé de donner accès à 100% des Rooms à partir de la TransporterRoom.
Contrainte : Utiliser la classe Random ainsi que la bonne méthode nextInt.
Aide : Dans le cas d'un tableau ou d'une ArrayList, il suffit de mettre les Room concernées au début, et de dire combien de Room il faut prendre en compte. Dans le cas d'une HashMap, il vous faudra trouver une autre astuce.
Ne pas oublier de lire les échanges ci-dessous pour mieux comprendre la bonne manière de réaliser cet exercice.
Après
avoir fini cette exercice, je pense ne pas l'avoir traité comme il
faut. J'ai vu que vous demandé d'expliquer la classe Random, nextInt et
seed.
Je ne l'ai cependant pas utilisé et j'ai créé ma méthode à partir de Math.random()*100%(vNombreDeRoom).
Somme-nous obligé de créer un objet Random pour créer notre méthode ?
Un étudiant a écrit :
.../...
De
toute façon, je me retrouve confronté au même problème dans le
TransporterRoom? Car, à moins que je ne crée un attribut de type Room[]
dans mon gameEngine où j'ai créé mes variables Room par exemple vJardin,
vDonjon etc, je ne pourrai pas créer de méthode retournant ce tableau,
qui pourra être appelée par la classe TransporterRoom lors d'un
changement de Room (goRoom()) ?
Merci, ca marche à présent. Mais je n'arrive pas encore à synthétiser de nombre aléatoire. Voici ce que je fais:
import java.util.Random;
public int getRandomNumber(){
return nextInt(7);
}
Le compilateur le dit qu'il ne trouve pas la méthode nextInt() ou nextInt(int). Dois-je appeler nextInt(7) sur quelque chose?
Bien sûr, comme pour toute méthode !
Si c'est une méthode statique, on écrit Classe.methode(); sinon on écrit objet.methode();
Dans le premier cas, methode doit appartenir à Classe, dans le deuxième cas, elle doit appartenir à la classe de objet.
(s'il vous arrive d'écrire juste methode(); c'est que vous ne suivez pas les directives qui vous ont été données, à savoir écrire this.methode();)
Bonjour,
Pour vérifier d'abord si j'ai bien compris ce qu'il faut faire dans l'exercice :
Le but est de faire en sorte que le joueur, lorsqu'il quitte une Transporter Room, se retrouve dans une autre salle aléatoirement.
Pour ça, il faut créer une classe TransporterRoom qui est une sorte de Room et y ajouter les méthodes qui sont dans le chapitre 9.11.
Il faut aussi créer une autre classe RoomRandomizer avec la méthode findRandomRoom().
Avec les questions posées précédemment, il faut importer la classe Random, utiliser la méthode nextInt(), et utiliser seed.
Ce que je ne comprends pas, c'est comment y parvenir à cause de différent point...
1. Je ne vois pas si la classe RoomRandomizer est une sorte de Room ou TransporterRoom.
2. Pour les attributs des deux nouvelles classes, je ne vois pas du tout quoi mettre.
3. La méthode nextInt() retourne un int mais je ne vois pas comment je pourrais m'en servir, parce que pour l'exercice 18.5, j'ai fait une HashMap et non un tableau... Donc faut-il plutôt faire un tableau ?
Vous avez bien compris.
1. Aucune des deux ! La TransporterRoom a juste besoin d'un objet RoomRandomizer pour fonctionner, ce qui répond aussi à votre question 2 pour TransporterRoom.
2. RoomRandomizer a besoin d'un tableau ou d'une liste de Room pour fonctionner, même si on peut passer une HashMap à son constructeur (voir votre question 3).
3. Le plus simple est effectivement de prévoir un tableau à l'exercice 7.18.5, mais vous pouvez aussi extraire une ArrayList de la HashMap grâce à sa méthode values() et au constructeur ArrayList(Collection).
Merci de votre réponse, cela m'a permis d'avancer. Malgré cela je rencontre d'autre difficulté.
J'essaye donc actuellement de répondre à cet exercice en gardant la HashMap au lieu d'un tableau comme vous avez dit que c'était possible.
En regardant la Javadoc de la méthode values(), je comprends qu'elle permet de retourner une Collection avec les valeurs de la HashMap, donc en l'occurrence, une Collection de Room.
Quant au constructeur de l'ArrayList(Collection), celui-ci demande une Collection en paramètre.
Donc pour récupérer une Room de l'ArrayList, j'utilise la méthode get() qui demande un int correspondant à l'index.
J'en ai donc déduit mon code suivant :
... code supprimé pour ne pas influencer les futurs lecteurs ...
Sauf qu'il m'indique l'erreur " incompatible type " au niveau du return.De plus, je ne comprends pas ce qu'est un seed et donc comment m'en servir...
Merci d'avance
Essayez de remplacer votre instruction return par return null;
Maintenant, ça compile, mais vous obtenez un warning vous
avertissant que vous utilisez des opérations non vérifiées donc non
sûres.
Cela provient de votre déclaration de vList : c'est une liste de quoi ???
Après avoir effectué la correction nécessaire, vous pouvez remettre votre instruction return et ça devrait compiler sans erreur ni warning.
Par contre, il faudrait améliorer votre calcul de vRandomNumber : que se passerait-il si, dans GameEngine, vous décidiez de retirer une pièce de la HashMap des Room ?
Pour comprendre l'utilité de la seed, veuillez lire le petit extrait de livre donné dans A SAVOIR EXPLIQUER juste après l'exercice 7.46.
Si vous ne comprenez pas quelque chose, demandez.
Merci encore de vos réponses, cela m'a permis comprendre où était mes erreurs.
Pour ma variable vList, j'ai oublié de préciser qu'il s'agissait d'une liste de Room lors de sa déclaration.
En ce qui concerne le calcul de vRandomNumber, si je rajoute des salles dans ma classe GameEngine, les
nouvelles salles ne seraient pas prise en compte et donc le nombre de
salle serait faussé. Pour éviter cela, il est préférable de regarder la
taille de la collection.
Pour le seed, si je ne me trompe
pas, il s'agit d'un algorithme qui permet de fournir des chiffres
"pseudo-aléatoire", c'est-à-dire qu'en choisissant un seed, les chiffres obtenus par cet algorithme seront toujours les mêmes.
Mais
comment doit on le choisir ? En prenant un chiffre en particulier,
lorsque je sors de ma salle, je me retrouve toujours dans la même
salle.
Vous avez effectivement bien compris ce qu'il fallait corriger.
Pour votre dernière question, en fonctionnement normal, on ne veut pas avoir toujours la même suite de nombres aléatoires : il ne faut donc pas fournir une seed ! (dans ce cas, la JVM utilise le nombre de millisecondes écoulées depuis le démarrage de l'ordinateur ce qui garantit à peu près un nombre "aléatoire")
Fournir une seed peut être utile en mode debug lorsque vous voulez reproduire un comportement problématique.
Bonjour,
Est-il obligatoire de créer la classe RoomRandomizer pour cet exercice ? J'ai réalisé l'exercice en écrivant le code qu'il faut visiblement mettre dans la classe RoomRandomizer (en utilisant Random, prendre une dans le getExit de TransporterRoom. Dans la mesure où ça marche parfaitement avec "moins" de code, je n'arrive pas à cerner l'utilité d'ajouter une telle classe (elle possède sûrement des avantages que je n'ai pas remarqué mais pour l'instant je sèche).
Bonjour monsieur,
Est-il vraiment nécessaire de créer la classe Transporter Room ? car d'après mon code j'en ai nullement besoin. La majorité de mes Rooms étant de bases des transporter rooms (ajout d'une variable pour définir si oui ou non elle le sont).
Merci d'avance.
Suite à un pb technique, je viens seulement d'être prévenu de votre message.
Oui, elle est indispensable, comme expliqué au chapitre 9.11 que vous avez dû lire.
L'objectif de cet exercice n'est pas d'ajouter une pièce qui vous
téléporte je ne sais où, mais de comprendre comment l'utilisation de
l'héritage et du polymorphisme vous permet ici d'ajouter cette
possibilité sans toucher au code existant, alors que
vous avez dû modifier bcp de choses dans le GameEngine et/ou le Player ...
Ma classe TransporterRoom est codé, simplement une fois que j'ai effectué le test dans la méthode goRoom() pour savoir si ma Room est ou non une TransporterRoom, je ne vois pas comment spécifier qu'il faut utiliser le getExit() de la sous-classe TransporterRoom et non le getExit() normal de la classe Room...
Merci de votre aide,
Suite à un pb technique, je viens seulement d'être prévenu de votre message.
Relisez le chapitre 9.11. Il n'y a besoin d'aucun test pour savoir si c'est une TransporterRoom. L'utilisation de la bonne version de getExit() est automatique grâce au polymorphisme.
Revoyez également votre cours sur l'héritage, la redéfinition, et les types déclaré et constaté.
Faudrait-il modifier la classe GameEngine et créer un tableau de Room qui sera un nouvel attribut, puis à chaque création de Room, nous l'affectons à un indice du tableau?
Puis nous pouvons alors donner en paramètre le tableau de Room à getExits() (dans la classe TransporterRoom) qui va à son tour donner à la classe RoomRandomizer pour utiliser findRandomRoom?
> Afin de générer une randomRoom, il faut déjà avoir connaissance de toutes les rooms existantes
>
Relisez l'exercice 7.18.5 : vous pouvez choisir les Room parmi lesquelles vous tirerez au sort.
> créer un tableau de Room qui sera un nouvel attribut, puis à
chaque création de Room, nous l'affectons à un indice du tableau?
>
Cela impliquerait de connaître le nombre de pièces et de changer la taille du tableau à chaque ajout/suppression de pièce.
Mais une ArrayList semble appropriée ...
> donner en paramètre le tableau de Room à getExits() (dans la classe TransporterRoom)
>
Surtout pas ! Il ne faut pas toucher à la signature de getExit (et non getExits) ; relisez le chapitre 9.11
> donner à la classe RoomRandomizer pour utiliser findRandomRoom
>
C'est l'objet de type TransporterRoom qui fera cela.
Un étudiant a écrit :
Bonjour,
dans cet exercice lorsque l'on sort de la room aléatoire doit on effacer l'historique des salles parcourus ou bien doit on pouvoir revenir avec le back ?
Un étudiant a écrit :
Je peux tout simplement appeler le RoomRandomizer.findRandomRoom() non?
Et je ne pourrais d'ailleurs pas faire pareil pour la hashmap de room qui se trouve dans game engine?
- Si vous créez plusieurs TransporterRoom,
vous pourriez conserver la possibilité d'utiliser des RoomRandomizer différents.
Le rendre static dénote une conception plus fermée, mais ce ne sera pas compté comme faux. - Il est effectivement peu probable que vous ayez plus d'un GameEngine,
donc pourquoi pas.
Mais la cohérence voudrait alors que tout soit static dans cette classe ; beaucoup de modifications en perspective ...
Un étudiant a écrit :
est-ce comme la trap door il faut spécifier la transporter Room dans la procédure createRooms() de la classe GameEngine?
Dans ce cas, faut- il également supprimer toutes les sorties qui lui sont associées?
Un étudiant a écrit :
Et s'il décide de faire retour dans cette nouvelle pièce, je lui empêche de le faire.
Ma question était : si le joueur rentre dans la transporter Room, et qu'il rentre "retour" au lieu d'une direction, doit il revenir dans la pièce avant la transporter Room ou faut-il le transporter aléatoirement ?
Réseaux sociaux